home *** CD-ROM | disk | FTP | other *** search
- /*==============================================================================
- Project: POV
-
- Version: 3
-
- File: aeUtils.c
-
- Description:
- AppleEvent utils & required aevt handlers.
- ------------------------------------------------------------------------------
- Author:
- Eduard [esp] Schwan
- ------------------------------------------------------------------------------
- from Persistence of Vision(tm) Ray Tracer
- Copyright 1996 Persistence of Vision Team
- ------------------------------------------------------------------------------
- NOTICE: This source code file is provided so that users may experiment
- with enhancements to POV-Ray and to port the software to platforms other
- than those supported by the POV-Ray Team. There are strict rules under
- which you are permitted to use this file. The rules are in the file
- named POVLEGAL.DOC which should be distributed with this file. If
- POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- Forum. The latest version of POV-Ray may be found there as well.
-
- This program is based on the popular DKB raytracer version 2.12.
- DKBTrace was originally written by David K. Buck.
- DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- ------------------------------------------------------------------------------
- Change History:
- 960120 [esp] Added core-handling skeleton
- ==============================================================================*/
-
- #define AEUTILS_C
-
- #include "AEUtils.h"
-
- #include <AppleEvents.h>
- #include <AERegistry.h>
- #include <CodeFragments.h> // kUnresolvedSymbolAddress
-
- #include "POVMac.h"
- #include "UtilLib.h"
- #include "StdFolder.h"
- #include "FileQueue.h"
- #include "AppPrefs.h"
- #include "Texteditor.h"
-
- #include "AEObjects.h"
- #include "Gestalt.h"
-
- #include "aeTok.h"
- #include "aeAppHdlr.h"
-
-
- // ---------------------------------------------------------------------
- Boolean gAppleScriptAvail=false;
-
- // ---------------------------------------------------------------------
- // utility to extract a short integer from an AEDesc
- #pragma segment Main
-
- OSErr ExtractShortFromAEDesc( AEDesc *theDesc,
- short *theShortPtr)
- {
- OSErr anError = noErr;
- AEDesc tempDesc;
-
- if (theDesc->descriptorType == typeShortInteger)
- {
-
- *theShortPtr = **((short **)theDesc->dataHandle);
- }
- else
- {
- /* if it wasn't a short to begin with, try and coerce it into a short */
- anError = AECoerceDesc(theDesc, typeShortInteger, &tempDesc);
- if (!anError)
- {
- /* it coerced. grab it */
- *theShortPtr = **((short **)tempDesc.dataHandle);
- AEDisposeDesc(&tempDesc);
- }
- }
- return anError;
- } // ExtractShortFromAEDesc
-
-
- // ---------------------------------------------------------------------
- // Send a System Seven Shutdown AppleEvent to the Finder to shut us all down
- void SendAEShutdown(void)
- {
- OSErr myErr;
- OSType theSignature;
- AppleEvent myAEvt, myReturnEvt;
- AEAddressDesc myServerAddress;
-
- theSignature = 'MACS'; // Finder signature.. of course!?
- myErr = AECreateDesc(typeApplSignature, (Ptr)&theSignature, 4, &myServerAddress);
- if (!myErr)
- myErr = AECreateAppleEvent(kAEFinderEvents, // Event Class
- kAEShutDown, // Event ID
- &myServerAddress, // Target Adr
- kAutoGenerateReturnID, // Return aevt ID
- kAnyTransactionID, // Trans ID
- &myAEvt); // fill me in
- if (!myErr)
- myErr = AESend(&myAEvt,
- &myReturnEvt,
- kAENoReply, // send mode
- kAENormalPriority, // send priority
- kNoTimeOut, // N timeout ticks
- NULL, // idleProcPtr
- NULL); // EventFilterProcPtr
- /* may as well clean up before we die :-) */
- if (!myErr)
- myErr = AEDisposeDesc(&myServerAddress);
- } // SendAEShutdown
-
-
- // ---------------------------------------------------------------------
- // Returns TRUE if all required AE parms were extracted OK
- #pragma segment Main
- OSErr GotRequiredAEParams(AppleEvent *theAppleEvent)
- {
- DescType typeCode;
- Size actualSize;
- OSErr err;
-
- err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
- &typeCode, NULL, 0, &actualSize); /* NULL ok here; need only function result */
- if (err == errAEDescNotFound)
- // we got all the required params: all is ok
- return noErr;
- else if (err == noErr)
- // found one left behind: error!
- return errAEEventNotHandled;
- else
- // some other oddity
- return err;
- } // GotRequiredAEParams
-
-
-
- // ---------------------------------------------------------------------
- // AE Handler - Oapp - If app run with no documents
- #pragma segment Main
- static pascal OSErr HandleAEOapp(AEDescList *aevt, AEDescList *reply, long refCon)
- {
- #pragma unused (reply,refCon)
- OSErr anError;
-
- /* We don't normally expect any parms, but check in case the client requires any */
- anError = GotRequiredAEParams(aevt);
-
- // if user hasn't already opened a window, open a new untitled window
- if (!anError && (gSrcWind_VRefNum == 0))
- DoFile_New();
-
- return anError;
- } // HandleAEOApp
-
-
- // ---------------------------------------------------------------------
- static OSErr DoAEOpenFile( FSSpecPtr theFSSpec,
- long index,
- long numFiles,
- Boolean forPrinting)
- {
- OSErr anError = noErr;
- FInfo theFileInfo;
- char theFname[32];
-
- // C version of filename
- BlockMove(theFSSpec->name, theFname, theFSSpec->name[0]+1);
- p2cstr((StringPtr)theFname);
-
- if ((**gDefltFilePrefs_h).progress >= eProgDebug)
- {
- printf("-d ODOC='%s'\n", theFname);
- }
-
- // better be a text file..
- // Note: We're in an AE Handler, so guaranteed to be System 7, so ok to call:
- FSpGetFInfo(theFSSpec, &theFileInfo);
- if (theFileInfo.fdType != 'TEXT')
- {
- (void)DisplayModalDialog(kdlog_CantOpenNonText,
- ok, 0, theFname, 0, ewcDoCentering, eSameAsPassedWindow);
- anError = 1;
- }
-
- /* Open the File here */
- if (!anError)
- {
- // Use this file to set anchor for any future SFGetFile opens...
- // in other words, if you drop one or more files onto POV-Ray, then
- // the next time you do a File-Open, the standard file dialog will
- // open at the directory of your dropped file, not the app directory.
- // (You're welcome Anton! [esp] :-)
- if (index == 1)
- SF_SetSFCurrent(theFSSpec);
-
- if ((**gDefltFilePrefs_h).progress >= eProgDebug)
- {
- printf("-d NumFiles=%d, DoingBatch=%d, DoingRender=%d\n",
- (int)numFiles, gDoingBatchODOCs, gDoingRender);
- }
-
- // already queued some, or
- // we're "printing" (which means auto-render)
- // so queue these too
- if (gDoingBatchODOCs || forPrinting)
- {
- FileQ_Put(theFSSpec);
- }
- else
- {
- // Don't open it if a file is already open and dirty (unsaved)
- if (gSrcWind_dirty)
- {
- (void)DisplayModalDialog(kdlog_CantOpenOverDirty,
- ok, 0, NULL, 0, ewcDoCentering, eSameAsPassedWindow);
- anError = 1; // no more files..
- }
- else
- { // ok to open
- if ((numFiles == 1) && !gDoingRender)
- {
- // Simple case, just one file to open, just open it and wait
- OpenTextFile(theFSSpec->name, theFSSpec->vRefNum, theFSSpec->parID, true/*UseDirID*/);
- }
- else
- {
- // mult. files dropped, or already rendering one.
- // put each file in a queue for later batch processing
- FileQ_Put(theFSSpec);
-
- // This is a sly way to tell DoRendering() to save the current
- // file being rendered automatically, before opening the next
- // file in the queue.
- if (gDoingRender)
- gDoingBatchODOCs = true;
- }
- } // else ok to add
- }
- } // if !error
- return anError;
- }
-
-
- // ---------------------------------------------------------------------
- // common ODOC/PDOC AE Handler
- #pragma segment Main
- static OSErr HandleAECommonOPDox( AEDescList *aevt,
- AEDescList *reply,
- long refCon,
- Boolean forPrinting)
- {
- #pragma unused(reply,refCon)
- OSErr anError = noErr;
- AEDesc fileListDesc;
- DescType actualType;
- long actualSize;
- AEKeyword actualKeyword;
- FSSpec oneFSSpec;
- long numFiles;
- long index;
-
- //
- // The "odoc" and "pdoc" messages contain a list of aliases as the direct paramater.
- // Extract the list, count the list's elements, and then process each file in turn.
- // Return any errors to the caller.
- //
-
- //
- // Extract the list of aliases into fileListDesc
- //
- anError = AEGetParamDesc(aevt, keyDirectObject, typeAEList, &fileListDesc);
-
- //
- // Make sure that's all we're supposed to do
- //
- if (!anError)
- anError = GotRequiredAEParams(aevt);
-
- //
- // Count the list elements
- //
-
- if (!anError)
- anError = AECountItems(&fileListDesc, &numFiles);
-
- //
- // Get each file from the list and process it. Even though the aevt
- // contains a list of aliases, the AppleEvent Manager will convert
- // each alias to an FSSpec if we ask it to.
- //
-
- for (index = 1; (index <= numFiles) && !anError; index++)
- {
- //
- // Pull the Nth file out of the aevt list
- //
-
- anError = AEGetNthPtr( &fileListDesc, index, typeFSS, &actualKeyword,
- &actualType, (Ptr)&oneFSSpec, sizeof(oneFSSpec), &actualSize);
-
- if (!anError && !AppIsQuitting())
- {
- //
- // Open or print the file
- //
-
- anError = DoAEOpenFile(&oneFSSpec, index, numFiles, forPrinting);
- }
- } // for
-
- //
- // All done with the list, throw it away
- //
-
- AEDisposeDesc(&fileListDesc);
-
- return anError;
-
- } // HandleAECommonOPDox()
-
-
-
- // ---------------------------------------------------------------------
- #pragma segment Main
- static pascal OSErr HandleAEOdoc( AEDescList *aevt,
- AEDescList *reply,
- long refCon)
- {
- return HandleAECommonOPDox(aevt, reply, refCon, false/*forPrint*/);
- } // HandleAEOdoc()
-
-
-
- // ---------------------------------------------------------------------
- #pragma segment Main
- static pascal OSErr HandleAEPdoc( AEDescList *aevt,
- AEDescList *reply,
- long refCon)
- {
- return HandleAECommonOPDox(aevt, reply, refCon, true/*forPrint*/);
- } // HandleAEPdoc()
-
-
- // ---------------------------------------------------------------------
- // AE Handler - Quit - Ask app to quit cleanly
- #pragma segment Main
- static pascal OSErr HandleAEQuit(AEDescList *aevt, AEDescList *reply, long refCon)
- {
- #pragma unused (reply,refCon)
-
- OSErr anError;
-
- /* We don't normally expect any parms, but check in case the client requires any */
- anError = GotRequiredAEParams(aevt);
-
- Stop_Flag = TRUE;
- SetAppQuit();
- return anError;
- } // HandleAEQuit
-
-
- // ---------------------------------------------------------------------
- // Handle any high level events (AppleEvents currently)
- void DoAEvts(EventRecord * theEventPtr)
- {
- AEProcessAppleEvent(theEventPtr);
- } // DoAEvts
-
-
- // ---------------------------------------------------------------------
- // Handles All Core suite AppleEvents, dispatches them to appropriate
- // object dispatcher (Application, Translator, etc.) This is done by
- // pre-extracting the class, and dispatching by class first, instead of
- // dispatching by AE command. This allows us to group all events for
- // a class in a single file. In other words, we dispatch by "app" or
- // "window" etc, instead of dispatching by "get data" or "close" etc.
- #pragma segment Main
-
- static pascal OSErr CoreSuiteDispatcher( AppleEvent *aevt,
- AppleEvent *reply,
- long refCon)
- {
- OSErr anError;
- DescType theTypeCode;
- AEEventClass theClassID;
- AEEventID theEventID;
- Size actualSize;
- AEDesc aeOspec = {typeNull, NULL};
- AEDesc aeToken = {typeNull, NULL};
-
- // extract the event class
- anError = AEGetAttributePtr(aevt, keyEventClassAttr, typeType, &theTypeCode,
- (Ptr)&theClassID, sizeof(theClassID), &actualSize);
- // extract the event ID
- if (!anError)
- anError = AEGetAttributePtr(aevt, keyEventIDAttr, typeType, &theTypeCode,
- (Ptr)&theEventID, sizeof(theEventID), &actualSize);
- // extract the direct parameter, the object specifier
- if (!anError)
- anError = AEGetKeyDesc(aevt, keyDirectObject, typeWildCard, &aeOspec);
-
- // go no further if errors
- if (anError)
- return anError;
-
- if (aeOspec.descriptorType == typeNull)
- {
- // null object (application), don't resolve it, no need to dispose it
- aeToken = aeOspec;
- theTypeCode = typeNull;
- }
- else
- {
- // resolve direct parm into a token
- anError = AEResolve(&aeOspec, kAEIDoMinimum, &aeToken);
- if (anError)
- return anError;
- theTypeCode = GetTokDescClass(aeToken); // get the dispatch class
- }
-
- // handle the token class appropriately
- switch (theTypeCode)
- {
- case typeNull: // Application's token class
- anError = AEAppDispatcher(theEventID, &aeToken, aevt, reply, refCon);
- break;
- // case cThing:
- // anError = ThingDispatcher(theEventID, &aeToken, aevt, reply, refCon);
- break;
- default:
- anError = errAEEventNotHandled;
- }
-
- // all done with these puppies...
- AEDisposeDesc(&aeOspec);
- AEDisposeDesc(&aeToken);
-
- return anError;
- } // CoreSuiteDispatcher
-
-
-
- // ---------------------------------------------------------------------
- // Install our special accessor handler routines into the dispatch table
- static void InstallAESuiteHandlers(void)
- {
- OSErr anError;
-
- //
- // The Core aevts
- //
-
- anError = AEInstallEventHandler(kAECoreSuite, typeWildCard,
- NewAEEventHandlerProc(CoreSuiteDispatcher), 0, false);
-
- //
- // debug catch-all
- //
-
- // debug, catch any unhandled events...
- /*
- anError = AEInstallEventHandler(typeWildCard, typeWildCard,
- (AEEventHandlerUPP)HandleAllTheRest, 0, false);
- */
-
- // Install any callback functions
- /*
- anError = AESetObjectCallbacks((compareProcPtr)NULL,
- NewOSLCountProc(CountEmProc),
- NewOSLDisposeTokenProc(DisposeTokenProc),
- (getMarkTokenProcPtr)NULL,
- (markProcPtr)NULL,
- (adjustMarksProcPtr)NULL,
- (getErrDescProcPtr)NULL);
- */
- } // InstallAESuiteHandlers
-
-
- // ---------------------------------------------------------------------
- // Install our AppleEvent handlers (above) so they can be called automatically
- // by AEProcessAppleEvent()
- void InstallAppleEvents(void)
- {
- OSErr anError = noErr;
- long gestaltResult;
-
- //
- // in case we're running an old AppleEvent System
- //
- anError = Gestalt(gestaltAppleEventsAttr, &gestaltResult);
- if (anError == noErr)
- {
- if (!((gestaltResult>>gestaltAppleEventsPresent) & 1)) // no AEvts on system?
- anError = -1; // need some Gestalt/AEvt error code, to be nice.
- else // is OSL in MacOS?
- if ((gestaltResult>>gestaltOSLInSystem) & 1)
- gAppleScriptAvail=TRUE;
- #if defined(powerc) || defined (__powerc)
- else if ((ProcPtr)AEResolve != (ProcPtr)kUnresolvedCFragSymbolAddress)
- #endif
- // NOT built-in, Then try to init the linked lib
- {
- anError = AEObjectInit();
- if (!anError)
- gAppleScriptAvail=TRUE;
- }
- }
-
- //
- // The REQUIRED aevts
- //
-
- if (!anError)
- anError = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
- NewAEEventHandlerProc(HandleAEOapp), 0, false);
- if (!anError)
- anError = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
- NewAEEventHandlerProc(HandleAEOdoc), 0, false);
- if (!anError)
- anError = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
- NewAEEventHandlerProc(HandleAEPdoc), 0, false);
- if (!anError)
- anError = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- NewAEEventHandlerProc(HandleAEQuit), 0, false);
-
- //
- // additional suites (Core, etc.) installed here
- //
- if (gAppleScriptAvail && !anError)
- InstallAESuiteHandlers();
-
- // if (anError) // DEBUG <>
- // (void)DisplayModalDialog(kdlog_GenericFatalErr, ok, 0,
- // "InstallAppleEvents: Cannot install AEvts", anError, ewcDoCentering, eMainDevice);
-
- } // InstallAppleEvents
-
-
-
-